#include "mlir/IR/DialectRegistry.h"
#include "mlir/Tools/mlir-opt/MlirOptMain.h"
// 导入 Func Dialect
#include "mlir/Dialect/Func/IR/FuncOps.h"
// 导入 MLIR 自带 Pass
#include "mlir/Transforms/Passes.h"
// 导入我们新建的 Dialect
#include "toy/ToyDialect.h"
#include "toy/ToyOps.h"

#include "mlir/IR/AsmState.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/Visitors.h"
#include "mlir/Parser/Parser.h"
#include "mlir/Support/FileUtilities.h"

#include "mlir/Dialect/Arith/IR/Arith.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ArrayRef.h"

using namespace mlir;
using namespace llvm;

int main(int argc, char ** argv) {
  /*
  MLIRContext ctx;

  ctx.loadDialect<toy::ToyDialect, func::FuncDialect>();

  // 创建 OpBuilder
  OpBuilder builder(&ctx);
  auto mod = builder.create<ModuleOp>(builder.getUnknownLoc());

  // 设置插入点
  builder.setInsertionPointToEnd(mod.getBody());

  // 创建 func
  auto i32 = builder.getI32Type();
  auto funcType = builder.getFunctionType({i32, i32}, {i32});
  auto func = builder.create<func::FuncOp>(builder.getUnknownLoc(), "test", funcType);

  // 添加基本块
  auto entry = func.addEntryBlock();
  auto args = entry->getArguments();

  // 设置插入点
  builder.setInsertionPointToEnd(entry);

  // 创建 arith.addi
  //auto addi = builder.create<arith::AddIOp>(builder.getUnknownLoc(), args[0], args[1]);
  OperationState state(builder.getUnknownLoc(), toy::AddOp::getOperationName());
  state.addTypes(builder.getI32Type());
  state.addOperands({args[0], args[1]});
  
  auto* op = builder.create(state);

  auto addi = dyn_cast<toy::AddOp>(op);

  // 创建 func.return
  builder.create<func::ReturnOp>(builder.getUnknownLoc(), ValueRange({addi}));
  mod->print(llvm::outs());
  */
  
  MLIRContext ctx;

  ctx.loadDialect<toy::ToyDialect, func::FuncDialect>();
  OpBuilder builder(&ctx);
  auto mod = builder.create<ModuleOp>(builder.getUnknownLoc());
  
  builder.setInsertionPointToEnd(mod.getBody());

  // 创建 func
  auto i32 = builder.getI32Type();
  auto funcType = builder.getFunctionType({i32, i32}, {i32});
  auto func = builder.create<func::FuncOp>(builder.getUnknownLoc(), "fuck", funcType);

  // 添加基本块
  auto entry = func.addEntryBlock();
  auto args = entry->getArguments();


  //ArrayRef<Value> inputs({args[0], args[1]});

  builder.setInsertionPointToEnd(entry);
  
  
  OperationState state(builder.getUnknownLoc(), toy::AddOp::getOperationName());
  state.addTypes(builder.getI32Type());
  state.addOperands({args[0], args[1]});
  //state.addOperands(inputs);
  
  auto* op = builder.create(state);

  state.operands.begin()->dump();
  auto addi = dyn_cast<toy::AddOp>(op);
  
  // 创建 arith.addi
  //auto addi = builder.create<toy::AddOp>(builder.getUnknownLoc(), inputs);
  //auto addi = builder.create<toy::AddOp>(builder.getUnknownLoc(), args[0], args[1]);

  // 创建 func.return
  builder.create<func::ReturnOp>(builder.getUnknownLoc(), ValueRange({addi}));
  mod->print(llvm::outs());
  
  /*
  //DialectRegistry registry;
  // 注册 Dialect
  //registry.insert<toy::ToyDialect, func::FuncDialect>();
  
  // // 注册两个 Pass
  // registerCSEPass();
  // registerCanonicalizerPass();
  // return asMainReturnCode(MlirOptMain(argc, argv, "toy-opt", registry));
  */
  return 0;
}
